package com.tyk.bookstore.front.auth.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.tyk.bookstore.front.auth.manager.AuthRedisManager;
import com.tyk.bookstore.front.auth.model.entity.MemberDo;
import com.tyk.bookstore.front.auth.model.query.LoginCodeQuery;
import com.tyk.bookstore.front.auth.model.query.LoginPwdQuery;
import com.tyk.bookstore.front.auth.model.query.MsgCodeSendWithBehaviorCheckQuery;
import com.tyk.bookstore.front.auth.repository.MemberAuthRepository;
import com.tyk.bookstore.front.auth.service.AuthService;
import com.tyk.bookstore.front.auth.strategy.enume.LoginType;
import com.tyk.bookstore.front.auth.strategy.factory.LoginActionFactory;
import com.tyk.bookstore.front.common.core.model.result.CommonResultEnum;
import com.tyk.bookstore.front.common.core.util.AssertUtil;
import com.tyk.bookstore.front.common.core.util.ComUtil;
import com.tyk.bookstore.front.common.other.code.behavior.manager.BehaviorCodeManager;
import com.tyk.bookstore.front.common.other.code.behavior.model.enume.SceneType;
import com.tyk.bookstore.front.common.other.code.msg.manager.MsgCodeManager;
import com.tyk.bookstore.front.common.security.util.SecurityUtil;
import com.tyk.bookstore.front.member.model.result.MemberResultEnum;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class AuthServiceImpl implements AuthService {

    private final AuthRedisManager authRedisManager;
    private final BehaviorCodeManager behaviorCodeManager;
    private final MsgCodeManager msgCodeManager;
    private final MemberAuthRepository memberAuthRepository;

    @Override
    public String sendMsgCodeWithBehaviorCheck(MsgCodeSendWithBehaviorCheckQuery query) {

        // 校验行为验证码
        boolean check = behaviorCodeManager.check(SceneType.LOGIN, query.getVerifyParam());
        AssertUtil.isTrue(check, CommonResultEnum.CODE_BEHAVIOR_ERROR);

        // 校验手机号/邮箱
        switch (query.getType()) {
            case PHONE_ALI -> {
                AssertUtil.isTrue(
                        memberAuthRepository.exist1Eq(
                                MemberDo::getPhone, query.getPrincipal(), MemberDo.class
                        ),
                        MemberResultEnum.PHONE_NOT_REGISTERED
                );
            }
            case EMAIL_QQ -> {
                AssertUtil.isTrue(
                        memberAuthRepository.exist1Eq(
                                MemberDo::getEmail, query.getPrincipal(), MemberDo.class
                        ),
                        MemberResultEnum.EMAIL_NOT_BOUND
                );
            }
        }

        // 发送消息验证码
        String code = msgCodeManager.sendCodeAsync(query.getType(), query.getPrincipal());

        // 生成并缓存消息验证码凭证
        String verifyCode = ComUtil.simUuid();
        authRedisManager.cacheLoginMsgCode(query.getType(), verifyCode, query.getPrincipal(), code);

        // 返回消息验证码凭证
        return verifyCode;

    }

    @Override
    public String loginByPwd(LoginPwdQuery query) {

        // 校验登录参数并获取会员ID
        LoginType type = query.getType().toLoginType();
        Long memberId = LoginActionFactory.build(type).getMemberId(query);

        // 生成并缓存token
        SecurityUtil.login(memberId);

        // 返回Token
        return SecurityUtil.getTokenValue();

    }

    @Override
    public String loginByCode(LoginCodeQuery query) {

        // 校验登录参数并获取会员ID
        LoginType type = query.getType().toLoginType();
        Long memberId = LoginActionFactory.build(type).getMemberId(query);

        // 生成并缓存token
        SecurityUtil.login(memberId);

        // 返回token
        return SecurityUtil.getTokenValue();

    }


    @Override
    public void logout() {
        StpUtil.logout();
    }


}
